package com.gd.iot.energy.service.dailymanage.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gd.iot.energy.code.ResponseCode;
import com.gd.iot.energy.consts.SystemConsts;
import com.gd.iot.energy.dao.systemadmin.AreaArchivesPOMapper;
import com.gd.iot.energy.exception.MyException;
import com.gd.iot.energy.po.systemadmin.AreaArchivesPO;
import com.gd.iot.energy.pojo.common.vo.ColumnVO;
import com.gd.iot.energy.pojo.common.vo.PageVO;
import com.gd.iot.energy.pojo.systemadmin.dto.AreaArchivesSaveDTO;
import com.gd.iot.energy.pojo.systemadmin.vo.AreaArchivesPageVO;
import com.gd.iot.energy.pojo.systemadmin.vo.AreaArchivesVO;
import com.gd.iot.energy.service.dailymanage.CustomerFeeService;
import com.gd.iot.energy.service.dailymanage.OperationfeeChargeService;
import com.gd.iot.energy.service.systemadmin.AreaOrganizationService;
import com.gd.iot.energy.util.CustomColumnUtil;
import com.gd.iot.energy.util.CustomStrUtil;
import com.gd.iot.energy.util.EnergyTypeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 营收管理
 */
@Service
public class CustomerFeeServiceImpl extends ServiceImpl<AreaArchivesPOMapper, AreaArchivesPO> implements CustomerFeeService {

    @Autowired
    private AreaOrganizationService areaOrganizationService;

    @Resource
    private AreaArchivesPOMapper areaArchivesPOMapper;

    @Autowired
    private OperationfeeChargeService operationfeeChargeService;

    /**
     * 表头配置文件
     */
    private static final String AREA_ARCHIVES_LIST_COLUMN_FILE_NAME = "dailymanage/area_archives_list.column";

    /**
     * 欠费、余额表头配置文件
     */
    private static final String BALANCE_AREA_ARCHIVES_LIST_COLUMN_FILE_NAME = "dailymanage/balance_area_archives_list.column";


    @Override
    public PageVO<AreaArchivesPageVO> getAreaArchivesVOPage(String customerSerialnumber, String customerName,
                                                            String customerPhone, Integer areaId,
                                                            Integer pageSize, Integer pageNum,
                                                            String orderColumn, String orderType,
                                                            SystemConsts.QueryFeeType queryFeeType, String customerFee) {
        IPage<AreaArchivesPO> page = new Page<>(pageNum, pageSize);
        QueryWrapper<AreaArchivesPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_del", SystemConsts.BooleanEnum.FALSE.value);
        if (StrUtil.isNotBlank(customerSerialnumber)) {
            queryWrapper.like("customer_serialnumber", customerSerialnumber.trim());
        }
        if (StrUtil.isNotBlank(customerName)) {
            queryWrapper.like("customer_name", customerName.trim());
        }
        if (StrUtil.isNotBlank(customerPhone)) {
            queryWrapper.like("customer_phone", customerPhone.trim());
        }
        if (StrUtil.isNotBlank(customerFee)) {
            BigDecimal balanceLessThanBigDecimal= CustomStrUtil.str2BigDecimalScala2(customerFee);
            queryWrapper.lt("customer_fee", balanceLessThanBigDecimal);
        }
        if (areaId != null) {
            List<Long> allChildAreaIds = areaOrganizationService.getAllChildAreaIds(areaId);
            if (CollUtil.isNotEmpty(allChildAreaIds)) {
                queryWrapper.in("measure_area_org", allChildAreaIds);
            }
        }

        if (StrUtil.isNotBlank(orderColumn) && StrUtil.isNotBlank(orderType)) {
            orderColumn = CustomStrUtil.humpToLine(orderColumn);
            queryWrapper.orderBy(true, orderType.equals(SystemConsts.OrderType.ASC.value), orderColumn);
        }
        EnergyTypeUtil.injectEnergyTypeWrapper(queryWrapper);
        IPage<AreaArchivesPO> areaArchivesPOPage = areaArchivesPOMapper.selectPage(page, queryWrapper);
        PageVO<AreaArchivesPageVO> pageVO = new PageVO<>();
        pageVO.setPageSize(pageSize);
        pageVO.setPageNum(pageNum);
        List<AreaArchivesPageVO> roleVOList = convertToAdminPageVOList(areaArchivesPOPage.getRecords(),queryFeeType);
        pageVO.setData(roleVOList);
        pageVO.setTotal(areaArchivesPOPage.getTotal());
        pageVO.setPages(areaArchivesPOPage.getPages());

        //表头
        List<ColumnVO> columns = CustomColumnUtil.getColumn(getConfigFileNameByQueryFeeType(queryFeeType));
        pageVO.setColumns(columns);
        return pageVO;
    }

    /**
     * 查询类型 返回不同的column列头
     * @param queryFeeType
     * @return
     */
    private String getConfigFileNameByQueryFeeType(SystemConsts.QueryFeeType queryFeeType) {
        switch (queryFeeType){
            case COMMON:
                return AREA_ARCHIVES_LIST_COLUMN_FILE_NAME;
            case BALANCE_QUERY:
            case ARREARS_QUERY:
                return BALANCE_AREA_ARCHIVES_LIST_COLUMN_FILE_NAME;
            default:
                return AREA_ARCHIVES_LIST_COLUMN_FILE_NAME;
        }
    }


    @Override
    public AreaArchivesVO getAreaArchive(Long id) {
        AreaArchivesPO areaArchivesPO = getAreaArchivesPOById(id);
        Map<Long, String> areaNamesMap = areaOrganizationService.getAreaNamesById(Arrays.asList(areaArchivesPO.getMeasureAreaOrg()));
        AreaArchivesVO areaArchivesVO = new AreaArchivesVO();
        areaArchivesVO.setId(id);
        areaArchivesVO.setCustomerName(areaArchivesPO.getCustomerName());
        areaArchivesVO.setCustomerPhone(areaArchivesPO.getCustomerPhone());
        areaArchivesVO.setCustomerTel(areaArchivesPO.getCustomerTel());
        areaArchivesVO.setReceNumber(CustomStrUtil.getDateNumber(SystemConsts.Prefix.SJBH));
        areaArchivesVO.setCustomerFee(areaArchivesPO.getCustomerFee().setScale(2, RoundingMode.HALF_UP));
        areaArchivesVO.setAreaName(areaNamesMap.get(areaArchivesPO.getMeasureAreaOrg()));
        return areaArchivesVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAreaArchive(AreaArchivesSaveDTO areaArchivesSaveDTO, SystemConsts.ChargeType chargeType) {
        if (areaArchivesSaveDTO.getId() == null
                || StrUtil.isBlank(areaArchivesSaveDTO.getReceNumber())
                || StrUtil.isBlank(areaArchivesSaveDTO.getFee())) {
            throw new MyException(ResponseCode.PARAMETER_REQUIRED);
        }

        //缴费金额
        BigDecimal fee = CustomStrUtil.str2BigDecimalScala2(areaArchivesSaveDTO.getFee());

        if (fee.compareTo(BigDecimal.ZERO) < 0) {
            throw new MyException(ResponseCode.FEE_NOT_LESS_THAN_ZERO);
        }

        AreaArchivesPO areaArchivesPO = getAreaArchivesPOById(areaArchivesSaveDTO.getId());

        //余额不能小于0
        BigDecimal customerFee;
        if(chargeType.equals(SystemConsts.ChargeType.pay)) {
            customerFee = areaArchivesPO.getCustomerFee().subtract(fee).setScale(2, RoundingMode.HALF_UP);
            if (customerFee.compareTo(BigDecimal.ZERO) < 0) {
                throw new MyException(ResponseCode.LEFT_FEE_NOT_ENOUGH);
            }
        }else{
            customerFee = areaArchivesPO.getCustomerFee().add(fee).setScale(2, RoundingMode.HALF_UP);
        }

        //更新记录
        AreaArchivesPO archivesPONew = new AreaArchivesPO();
        archivesPONew.setId(areaArchivesPO.getId());
        archivesPONew.setCustomerFee(customerFee);
        areaArchivesPOMapper.updateById(archivesPONew);

        //记录日志
        operationfeeChargeService.saveOperationfeeCharge(SystemConsts.OperatingfeeSettlementTypeEnum.AUTO,
                fee, SystemConsts.OperatingfeePaywayEnum.CASH,areaArchivesPO.getEnergyType(),
                chargeType,customerFee,areaArchivesPO.getId(),areaArchivesSaveDTO.getReceNumber());

        return true;
    }

    /**
     * 通过id获取AreaArchivesPO对象
     *
     * @param id
     * @return
     */
    private AreaArchivesPO getAreaArchivesPOById(Long id) {
        QueryWrapper<AreaArchivesPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        queryWrapper.eq("is_del", SystemConsts.BooleanEnum.FALSE.value);
        EnergyTypeUtil.injectEnergyTypeWrapper(queryWrapper);
        AreaArchivesPO areaArchivesPO = areaArchivesPOMapper.selectOne(queryWrapper);
        if (areaArchivesPO == null) {
            throw new MyException(ResponseCode.RECORD_NOT_EXIST);
        }
        return areaArchivesPO;
    }

    /**
     * po转vo
     *
     * @param records
     * @param queryFeeType
     * @return
     */
    private List<AreaArchivesPageVO> convertToAdminPageVOList(List<AreaArchivesPO> records, SystemConsts.QueryFeeType queryFeeType) {
        List<AreaArchivesPageVO> res = new ArrayList<>(records.size());
        AreaArchivesPageVO areaArchivesPageVO;
        List<Long> areaIds = records.stream()
                .map(AreaArchivesPO::getMeasureAreaOrg)
                .collect(Collectors.toList());
        Map<Long, String> areaIdNameMap = areaOrganizationService.getAreaNamesById(areaIds);
        long i = 1;
        for (AreaArchivesPO record : records) {
            areaArchivesPageVO = new AreaArchivesPageVO();
            areaArchivesPageVO.setAreaName(areaIdNameMap.get(record.getMeasureAreaOrg()));
            areaArchivesPageVO.setSerialNum(i);
            areaArchivesPageVO.setId(record.getId());
            areaArchivesPageVO.setCustomerName(record.getCustomerName());
            areaArchivesPageVO.setCustomerSerialnumber(record.getCustomerSerialnumber());
            areaArchivesPageVO.setCustomerPhone(record.getCustomerPhone());
            if(queryFeeType.equals(SystemConsts.QueryFeeType.ARREARS_QUERY)
                    ||queryFeeType.equals(SystemConsts.QueryFeeType.BALANCE_QUERY)){
                areaArchivesPageVO.setCustomerFee(record.getCustomerFee()==null
                        ?null
                        :record.getCustomerFee().setScale(2,RoundingMode.HALF_UP).toPlainString());
            }
            res.add(areaArchivesPageVO);
            i++;
        }
        return res;
    }

    @Override
    public List<AreaArchivesPO> selectByParams(String customerSerialnumber, String customerName, String customerType, Integer areaId, String archivesAddress) {
        QueryWrapper<AreaArchivesPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_del", SystemConsts.BooleanEnum.FALSE.value);
        EnergyTypeUtil.injectEnergyTypeWrapper(queryWrapper);

        if (StrUtil.isNotBlank(customerSerialnumber)) {
            queryWrapper.like("customer_serialnumber", customerSerialnumber.trim());
        }
        if (StrUtil.isNotBlank(customerName)) {
            queryWrapper.like("customer_name", customerName.trim());
        }
        if (StrUtil.isNotBlank(customerType)) {
            queryWrapper.like("customer_type", customerType.trim());
        }
        if (StrUtil.isNotBlank(archivesAddress)) {
            queryWrapper.like("serialnumber", archivesAddress.trim());
        }

        if (areaId != null) {
            List<Long> allChildAreaIds = areaOrganizationService.getAllChildAreaIds(areaId);
            if (CollUtil.isNotEmpty(allChildAreaIds)) {
                queryWrapper.in("measure_area_org", allChildAreaIds);
            }
        }
        return areaArchivesPOMapper.selectList(queryWrapper);
    }
}
